package package01;


import package01.dao.ChatDao;
import package01.dao.ChatDaoImp;
import package01.handler.ServerHandler;
import package01.pojo.Chat;
import package01.utils.DateUtil;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;

/**
 * @param
 * @Description 服务器端
 * @Return
 * @Author zzj
 * @Date 2020/7/21 18:22
 **/
public class Server {
    public static void main(String[] args) {
        // ServerSocket：服务器端套接字
        ServerSocket server = null;
        try {
            // 实例化服务器端套接字，端口号9000
            server = new ServerSocket(9000);

            // 聊天室初始化（ServerInit:实现了Runable接口）： 加载数据库中所有的聊天信息
            ServerInit init = new ServerInit();
            // 初始化init()
            init.init();
            // 为init开启线程public Thread(Runnable target)：
            new Thread(init).start();   // 1s休眠一次，同时flush，将status变为1
            // 循环监听新的消息，并将socket流反序列化成chat对象，存储到数据库中。
            // 死循环
            while (true) {
                // 打印监听中
                System.out.println("监听中"); // 监听后开始一个线程
                // accept 接受客户端的连接请求,并返回一个套接字.如果没有连接到客户端,线程处于阻塞状态,程序无法执行下去
                Socket socket = server.accept();
                // 开启一个线程和客户端进行通信  将接收到的socket传入ServerHandler
                Thread t = new Thread(new ServerHandler(socket));
                // 启动线程并执行run
                t.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭ServerSocket
                server.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    static class ServerInit implements Runnable {

        private String filePath = "C:\\Users\\ASUS\\Desktop\\上午笔记\\chat.txt";

        @Override
        public void run() {
            // 循环刷新
            while (true) {
                flush();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        // 刷新
        public void flush() {
            ChatDao chatDao = new ChatDaoImp();
            List<Chat> list = chatDao.findListByNotRead("0");
            // 改成已读
            chatDao.updateState(list);
            // 写入文件
            appendLine(list);
        }


        /**
         * @param
         * @Description 初始化ServerInit，从数据库中找到所有status=1（已读）的数据，封装成对象传给集合list
         * @Return void
         * @Author zzj
         * @Date 2020/7/21 18:59
         **/
        private void init() {
            // 查询所有
            ChatDao chatDao = new ChatDaoImp();
            // 从数据库中找到所有status=1（已读）的数据，封装成对象传给集合list
            List<Chat> list = chatDao.findListByNotRead("1");
            appendLine(list);
        }

        /**
         * @param list
         * @Description 1. List集合已经存放了chat对象（有数据库已读信息封装而来）
         * 2. 将集合中的对象按指定格式输出到chat.txt中
         * @Return void
         * @Author zzj
         * @Date 2020/7/21 19:10
         **/
        // 向文件中追加新的聊天信息
        private void appendLine(List<Chat> list) {
            // 写入文件
            // 文件输出流1
            FileOutputStream fo = null;
            // 字符串缓冲流
            BufferedWriter writer = null;

            try {
                // 因为要分次将用户已读的数据追加到chat.txt中，所以不能够覆盖，要加上append：true
                fo = new FileOutputStream(filePath, true);
                // public BufferedWriter(Writer out)
                writer = new BufferedWriter(new OutputStreamWriter(fo));

                // 时间@[某某]说:
                String line = "";
                // 遍历 list集合
                for (Chat chat : list) {
                    line = String.format(
                            "%s@[%s]说: %s",
                            DateUtil.toDateStr(chat.getCreateTime()),
                            chat.getNickname(),
                            chat.getMessage()
                    );
                    // 写入文件
                    writer.write(line);
                    // 换行
                    writer.newLine();
                    // 清空缓冲区
                    writer.flush();
                }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    fo.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
